#!/usr/bin/env node
/**
 * 字段规范验证和纠正工具 V2
 * 优化版本：减少硬编码，更通用的处理逻辑
 *
 * 核心理念：
 * 1. 纠正后的文档是真理源，AI可直接使用无需推理
 * 2. 适配多种未知组件，避免硬编码
 * 3. 基于PB系统规范进行智能分组
 */

const fs = require('fs');
const path = require('path');

// ========== 规则库定义（基于PB系统规范）==========

/**
 * 字段命名映射规则（通用规范）
 */
const FIELD_NAME_MAPPING = {
  // 背景相关
  backgroundColor: 'bgColor',
  backgroundColorOpacity: 'bgColorOpacity',
  backgroundImage: 'bgImg',
  hasBackground: 'hasBg',

  // 标题相关
  titleFontColor: 'titleColor',
  titleSize: 'titleFontSize',

  // 静态文本
  staticTextColor: 'staticTitleFontColor',
  staticTextSize: 'staticTitleFontSize',

  // 边距相关
  marginTop: 'topMargin',
  marginBottom: 'bottomMargin',
  marginHorizontal: 'horizontalOutterMargin',
  paddingTop: 'topPadding',
  paddingBottom: 'bottomPadding',
  paddingHorizontal: 'horizontalInnerPadding',

  // 其他常见错误
  showMoreButton: 'showMore',
  titleBarVisible: 'showTitleBar',
  borderRadius: 'cornerRadius',
  moreButtonText: 'moreText',
  jumpUrl: 'jumpLink',
};

/**
 * 字段数据类型规则（基于PB系统数据类型）
 */
const FIELD_TYPE_RULES = {
  // Boolean类型（显示控制）
  visible: { type: 'boolean', default: true },
  showTitle: { type: 'boolean', default: true },
  showMore: { type: 'boolean', default: true },
  showTitleBar: { type: 'boolean', default: true },
  showDesc: { type: 'boolean', default: true },
  closable: { type: 'boolean', default: false },

  // Y/N类型（样式控制）
  isTitleFontBold: { type: 'Y|N', default: 'Y' },
  isTitleFontItalic: { type: 'Y|N', default: 'N' },
  isTitleFontUnderline: { type: 'Y|N', default: 'N' },
  isStaticTitleFontBold: { type: 'Y|N', default: 'N' },
  isStaticTitleFontItalic: { type: 'Y|N', default: 'N' },
  hasBg: { type: 'Y|N', default: 'N' },
  needLogin: { type: 'Y|N', default: 'N' },
  allowUserEdit: { type: 'Y|N', default: 'N' },

  // 图片数组类型
  titleIcon: {
    type: 'imageArray',
    structure: '[{src: "", width: 0, height: 0, iconName: "", link: "", linkId: "", linkType: ""}]',
  },
  moreIcon: {
    type: 'imageArray',
    structure: '[{src: "", width: 0, height: 0, iconName: "", link: "", linkId: "", linkType: ""}]',
  },

  // 背景图对象类型
  bgImg: {
    type: 'imageObject',
    structure: '{src: "", width: 0, height: 0}',
  },

  // 字符串类型（颜色）
  bgColor: { type: 'string', default: '#ffffff' },
  titleColor: { type: 'string', default: '#242424' },
  moreColor: { type: 'string', default: '#6A52E8' },
  staticTitleFontColor: { type: 'string', default: '#545454' },

  // 数字类型（透明度）
  bgColorOpacity: { type: 'number', default: 100 },
  titleColorOpacity: { type: 'number', default: 100 },
  moreColorOpacity: { type: 'number', default: 100 },

  // 字符串类型（尺寸）
  titleFontSize: { type: 'string', default: '16' },
  titleFontWeight: { type: 'string', default: '600' },
  titleLineHeight: { type: 'string', default: '24' },
  topMargin: { type: 'string', default: '0' },
  bottomMargin: { type: 'string', default: '0' },
  horizontalOutterMargin: { type: 'string', default: '0' },
  topPadding: { type: 'string', default: '16' },
  bottomPadding: { type: 'string', default: '16' },
  horizontalInnerPadding: { type: 'string', default: '16' },
  cornerRadius: { type: 'string', default: '8' },
  borderRadius: { type: 'string', default: '8' },
};

/**
 * 配套字段规则
 */
const FIELD_PAIRING_RULES = {
  // 颜色必须配透明度
  bgColor: ['bgColorOpacity'],
  titleColor: ['titleColorOpacity', 'titleFontColorOpacity'],
  moreColor: ['moreColorOpacity'],

  // 字体配样式
  titleFontSize: ['isTitleFontBold', 'isTitleFontItalic', 'isTitleFontUnderline'],

  // 背景配套
  hasBg: ['bgType', 'bgColor', 'bgColorOpacity'],

  // 链接配套
  jumpLink: ['jumpLinkType', 'jumpLinkId'],
};

/**
 * 基于字段名智能推断所属面板
 * 这个函数使用模式匹配而非硬编码
 */
function inferPanelByFieldName(fieldName) {
  const name = fieldName.toLowerCase();

  // 可见性控制
  if (name === 'visible') return 'header';

  // 基础信息
  if (name.includes('title') && !name.includes('color') && !name.includes('font')) return 'basicInfo';
  if (name.includes('show') || name.includes('display')) return 'basicInfo';
  if (name === 'moretext' || name === 'jumplink') return 'basicInfo';

  // 标题样式
  if (name.includes('title') && (name.includes('color') || name.includes('font') || name.includes('size'))) {
    return 'titleStyle';
  }

  // 静态文本样式
  if (name.includes('static')) return 'staticTextStyle';

  // 组件样式（Component Style）
  if (name.includes('margin') || name.includes('padding')) return 'componentStyle';
  if (name.includes('bg') || name.includes('background')) return 'componentStyle';
  if (name.includes('border') || name.includes('corner') || name.includes('radius')) return 'componentStyle';

  // 分组设置
  if (name.includes('group') || name.includes('profile')) return 'groupSetting';
  if (name.includes('needlogin') || name.includes('targetlabel')) return 'groupSetting';
  if (name.includes('android') || name.includes('ios')) return 'groupSetting';

  // 发布信息
  if (name.includes('publish') || name.includes('expire')) return 'publishInfo';

  // 事件埋点
  if (name.includes('floor') || name.includes('event')) return 'eventReportSetting';

  // 默认归入basicInfo
  return 'basicInfo';
}

/**
 * 必需的公共字段（基于600_BIZ规范）
 */
const REQUIRED_PUBLIC_FIELDS = {
  // Content公共字段
  visible: { section: 'content', belongTo: 'header', type: 'boolean', default: true },
  floorName: { section: 'content', belongTo: 'eventReportSetting', type: 'string', default: '' },
  groupSetting: { section: 'content', belongTo: 'groupSetting', type: 'array', default: [] },
  profileSetting: { section: 'content', belongTo: 'groupSetting', type: 'array', default: [] },
  targetLabel: { section: 'content', belongTo: 'groupSetting', type: 'string', default: '' },
  needLogin: { section: 'content', belongTo: 'groupSetting', type: 'Y|N', default: 'N' },
  androidValue: { section: 'content', belongTo: 'groupSetting', type: 'object', default: { miniVersion: '', maxVersion: '' } },
  iosValue: { section: 'content', belongTo: 'groupSetting', type: 'object', default: { miniVersion: '', maxVersion: '' } },
  publishTime: { section: 'content', belongTo: 'publishInfo', type: 'string', default: '' },
  expireTime: { section: 'content', belongTo: 'publishInfo', type: 'string', default: '' },

  // Style公共字段（Component Style）
  topMargin: { section: 'style', belongTo: 'componentStyle', type: 'string', default: '0' },
  bottomMargin: { section: 'style', belongTo: 'componentStyle', type: 'string', default: '0' },
  horizontalOutterMargin: { section: 'style', belongTo: 'componentStyle', type: 'string', default: '0' },
  topPadding: { section: 'style', belongTo: 'componentStyle', type: 'string', default: '16' },
  bottomPadding: { section: 'style', belongTo: 'componentStyle', type: 'string', default: '16' },
  horizontalInnerPadding: { section: 'style', belongTo: 'componentStyle', type: 'string', default: '16' },
  hasBg: { section: 'style', belongTo: 'componentStyle', type: 'Y|N', default: 'N' },
  bgType: { section: 'style', belongTo: 'componentStyle', type: 'enum', values: ['Color', 'Image'], default: 'Color' },
  bgColor: { section: 'style', belongTo: 'componentStyle', type: 'string', default: '#ffffff' },
  bgColorOpacity: { section: 'style', belongTo: 'componentStyle', type: 'number', default: 100 },
  bgImg: { section: 'style', belongTo: 'componentStyle', type: 'imageObject', structure: '{src: "", width: 0, height: 0}' },
  cornerRadius: { section: 'style', belongTo: 'componentStyle', type: 'string', default: '8' },
  borderRadius: { section: 'style', belongTo: 'componentStyle', type: 'string', default: '8' },
};

// ========== 核心验证和纠正逻辑 ==========

class FieldValidator {
  constructor() {
    this.errors = [];
    this.warnings = [];
    this.corrections = [];
    this.addedFields = [];
  }

  /**
   * 验证并纠正单个字段
   */
  validateAndCorrectField(fieldName, fieldDef) {
    let correctedField = { ...fieldDef };
    let correctedName = fieldName;

    // 1. 检查并纠正字段名称
    if (FIELD_NAME_MAPPING[fieldName]) {
      const correctName = FIELD_NAME_MAPPING[fieldName];
      this.corrections.push({
        type: 'name',
        original: fieldName,
        corrected: correctName,
        reason: `标准命名规范：${fieldName} → ${correctName}`,
      });
      correctedName = correctName;
    }

    // 2. 检查并纠正数据类型
    const typeRule = FIELD_TYPE_RULES[correctedName];
    if (typeRule) {
      const originalType = this.extractType(fieldDef);
      const correctType = this.formatType(typeRule);

      if (originalType !== correctType) {
        this.corrections.push({
          type: 'dataType',
          field: correctedName,
          original: originalType,
          corrected: correctType,
          reason: `数据类型规范：${originalType} → ${correctType}`,
        });
        correctedField.type = correctType;

        if (typeRule.structure) {
          correctedField.structure = typeRule.structure;
        }
      }

      if (typeRule.default !== undefined && !correctedField.default) {
        correctedField.default = typeRule.default;
      }
    }

    // 3. 检查配套字段
    if (FIELD_PAIRING_RULES[correctedName]) {
      const requiredPairs = FIELD_PAIRING_RULES[correctedName];
      requiredPairs.forEach((pairField) => {
        if (!this.allFields[pairField]) {
          this.addedFields.push({
            name: pairField,
            type: FIELD_TYPE_RULES[pairField],
            reason: `配套字段：${correctedName} 需要配套 ${pairField}`,
          });
        }
      });
    }

    // 4. 智能推断面板归属
    const belongTo = correctedField.belongTo || inferPanelByFieldName(correctedName);
    correctedField.belongTo = belongTo;

    // 5. 确定章节归属
    if (!correctedField.section) {
      // 基于belongTo推断section
      if (['componentStyle', 'titleStyle', 'staticTextStyle', 'cardStyle'].includes(belongTo)) {
        correctedField.section = 'style';
      } else {
        correctedField.section = 'content';
      }
    }

    return { name: correctedName, definition: correctedField };
  }

  extractType(fieldDef) {
    if (typeof fieldDef === 'string') {
      const match = fieldDef.match(/\[([^\]]+)\]/);
      return match ? match[1].toLowerCase() : 'string';
    }
    if (fieldDef.type) {
      return fieldDef.type;
    }
    return 'unknown';
  }

  formatType(typeRule) {
    if (typeRule.type === 'boolean') return 'boolean';
    if (typeRule.type === 'Y|N') return "'Y'|'N'";
    if (typeRule.type === 'string') return 'string';
    if (typeRule.type === 'number') return 'number';
    if (typeRule.type === 'array') return 'array';
    if (typeRule.type === 'object') return 'object';
    if (typeRule.type === 'imageArray') return 'Array<ImageObject>';
    if (typeRule.type === 'imageObject') return 'ImageObject';
    if (typeRule.type === 'enum' && typeRule.values) {
      return typeRule.values.map((v) => `'${v}'`).join('|');
    }
    return typeRule.type;
  }

  checkRequiredFields(fields) {
    const missingFields = [];

    Object.entries(REQUIRED_PUBLIC_FIELDS).forEach(([fieldName, fieldDef]) => {
      if (!fields[fieldName]) {
        missingFields.push({
          name: fieldName,
          ...fieldDef,
          reason: `必需的${fieldDef.section === 'content' ? 'Content' : 'Style'}公共字段 (${fieldDef.belongTo}面板)`,
        });
      }
    });

    return missingFields;
  }

  generateReport() {
    return {
      summary: {
        totalErrors: this.errors.length,
        totalWarnings: this.warnings.length,
        totalCorrections: this.corrections.length,
        totalAddedFields: this.addedFields.length,
      },
      errors: this.errors,
      warnings: this.warnings,
      corrections: this.corrections,
      addedFields: this.addedFields,
      timestamp: new Date().toISOString(),
    };
  }
}

// ========== 文档解析和生成 ==========

/**
 * 解析方案文档，提取字段定义
 */
function parseDocument(content) {
  const fields = {};
  const lines = content.split('\n');

  let inContentSection = false;
  let inStyleSection = false;

  for (let i = 0; i < lines.length; i++) {
    const line = lines[i];

    // 检测章节
    if (line.includes('Content') && (line.includes('可配置内容') || line.includes('配置内容'))) {
      inContentSection = true;
      inStyleSection = false;
      continue;
    }
    if (line.includes('Style') && (line.includes('可配置内容') || line.includes('配置内容'))) {
      inContentSection = false;
      inStyleSection = true;
      continue;
    }
    if (line.startsWith('##') && !line.startsWith('###')) {
      inContentSection = false;
      inStyleSection = false;
    }

    // 解析字段定义
    if ((inContentSection || inStyleSection) && line.includes('○')) {
      const cleanLine = line.trim();
      const match = cleanLine.match(/○\s*(\w+)\s*:\s*\[([^\]]+)\](.*)/);
      if (match) {
        const fieldName = match[1];
        const fieldType = match[2];
        const description = match[3].trim();

        fields[fieldName] = {
          type: fieldType,
          description: description,
          section: inContentSection ? 'content' : 'style',
        };
      }
    }
  }

  return fields;
}

/**
 * 生成纠正后的文档（更智能的分组）
 */
function generateCorrectedDocument(originalContent, correctedFields, addedFields, report) {
  let content = originalContent;

  // 1. 应用字段名和类型纠正
  report.corrections.forEach((correction) => {
    if (correction.type === 'name') {
      const regex = new RegExp(`○\\s+${correction.original}:`, 'g');
      content = content.replace(regex, `○ ${correction.corrected}:`);
    } else if (correction.type === 'dataType') {
      const regex = new RegExp(`○\\s+${correction.field}:\\s*\\[[^\\]]+\\]`, 'g');
      content = content.replace(regex, (match) => {
        return match.replace(/\[[^\]]+\]/, `[${correction.corrected}]`);
      });
    }
  });

  // 2. 收集所有字段并按面板分组
  const allFields = { ...correctedFields };
  addedFields.forEach(field => {
    allFields[field.name] = field;
  });

  // 按section和belongTo分组
  const contentPanels = {};
  const stylePanels = {};

  Object.entries(allFields).forEach(([fieldName, field]) => {
    const section = field.section || (field.belongTo === 'componentStyle' ? 'style' : 'content');
    const belongTo = field.belongTo || inferPanelByFieldName(fieldName);

    if (section === 'style') {
      if (!stylePanels[belongTo]) {
        stylePanels[belongTo] = [];
      }
      stylePanels[belongTo].push({ name: fieldName, ...field });
    } else {
      if (!contentPanels[belongTo]) {
        contentPanels[belongTo] = [];
      }
      contentPanels[belongTo].push({ name: fieldName, ...field });
    }
  });

  // 3. 重新组织Style章节 - 确保Component Style字段合并
  const styleStart = content.indexOf('### Style 可配置内容');
  if (styleStart !== -1) {
    const nextSection = content.indexOf('\n##', styleStart + 1);
    const styleEnd = nextSection !== -1 ? nextSection : content.length;

    // 保留非Component Style的原有内容
    const styleContent = content.substring(styleStart, styleEnd);
    let preservedGroups = [];

    // 查找并保留非Component Style相关的分组
    const groupPattern = /●\s*([^：:\n]+)[：:][\s\S]*?(?=●|##|$)/g;
    let match;
    while ((match = groupPattern.exec(styleContent)) !== null) {
      const groupName = match[1].trim();
      // 不是Component Style相关的分组才保留
      if (!groupName.includes('组件') && !groupName.includes('Component') &&
          !groupName.includes('Padding') && !groupName.includes('背景') &&
          !groupName.includes('边框')) {
        preservedGroups.push(match[0]);
      }
    }

    // 构建新的Style章节
    let newStyleSection = '### Style 可配置内容\n\n';

    // 先添加保留的分组
    preservedGroups.forEach(group => {
      newStyleSection += group + '\n';
    });

    // 添加Component Style分组（如果有）
    if (stylePanels['componentStyle'] && stylePanels['componentStyle'].length > 0) {
      newStyleSection += '● Component Style（组件样式）：\n';

      // 定义字段顺序
      const fieldOrder = [
        'topPadding', 'bottomPadding', 'horizontalInnerPadding',
        'topMargin', 'bottomMargin', 'horizontalOutterMargin',
        'hasBg', 'bgType', 'bgColor', 'bgColorOpacity', 'bgImg',
        'cornerRadius', 'borderRadius'
      ];

      const processedFields = new Set();

      // 按顺序输出
      fieldOrder.forEach(fieldName => {
        const field = stylePanels['componentStyle'].find(f => f.name === fieldName);
        if (field) {
          newStyleSection += `    ○ ${field.name}: [${formatFieldType(field)}] ${field.description || getFieldDescription(field)}\n`;
          processedFields.add(fieldName);
        }
      });

      // 输出其他未在顺序中的字段
      stylePanels['componentStyle'].forEach(field => {
        if (!processedFields.has(field.name)) {
          newStyleSection += `    ○ ${field.name}: [${formatFieldType(field)}] ${field.description || getFieldDescription(field)}\n`;
        }
      });
    }

    // 替换Style章节
    content = content.substring(0, styleStart) + newStyleSection + content.substring(styleEnd);
  }

  // 4. 补充缺失的Content字段
  let contentAdditions = '';
  Object.entries(contentPanels).forEach(([panelName, fields]) => {
    // 检查是否已存在
    if (!content.includes(getPanelTitle(panelName))) {
      contentAdditions += `\n● ${getPanelTitle(panelName)}：\n`;
      fields.forEach(field => {
        contentAdditions += `    ○ ${field.name}: [${formatFieldType(field)}] ${field.description || getFieldDescription(field)}\n`;
      });
    }
  });

  if (contentAdditions) {
    // 在Content章节末尾添加
    const contentEnd = content.indexOf('### Style 可配置内容');
    if (contentEnd !== -1) {
      content = content.substring(0, contentEnd) + contentAdditions + '\n' + content.substring(contentEnd);
    }
  }

  // 5. 添加纠正报告摘要
  const reportSummary = `
# 字段纠正报告

生成时间：${new Date().toISOString()}

## 纠正统计
- 字段名称纠正：${report.corrections.filter((c) => c.type === 'name').length} 项
- 数据类型纠正：${report.corrections.filter((c) => c.type === 'dataType').length} 项
- 新增必需字段：${report.addedFields.length} 项

## 说明
此文档已根据PB系统规范自动纠正，可作为AI生成组件的真理源直接使用。

---

`;

  return reportSummary + content;
}

function formatFieldType(field) {
  if (field.type === "'Y'|'N'") return "'Y'|'N'";
  if (field.type === 'imageObject' || field.type === 'ImageObject') return 'ImageObject';
  if (field.type === 'imageArray' || field.type === 'Array<ImageObject>') return 'Array<ImageObject>';
  return field.type || 'string';
}

function getFieldDescription(field) {
  const descriptions = {
    visible: '组件是否可见',
    floorName: '楼层名称（用于事件埋点）',
    groupSetting: '用户组设置',
    profileSetting: '用户档案设置',
    targetLabel: '目标标签',
    needLogin: '是否需要登录',
    androidValue: 'Android版本限制',
    iosValue: 'iOS版本限制',
    publishTime: '发布开始时间',
    expireTime: '发布结束时间',
    topMargin: '组件顶部外边距',
    bottomMargin: '组件底部外边距',
    horizontalOutterMargin: '组件水平外边距',
    topPadding: '组件顶部内边距',
    bottomPadding: '组件底部内边距',
    horizontalInnerPadding: '组件水平内边距',
    hasBg: '是否有背景',
    bgType: '背景类型（颜色或图片）',
    bgColor: '背景颜色',
    bgColorOpacity: '背景颜色透明度',
    bgImg: '背景图片',
    cornerRadius: '圆角大小',
    borderRadius: '边框圆角',
  };
  return descriptions[field.name] || '';
}

function getPanelTitle(panelName) {
  const titles = {
    header: '可见性控制',
    eventReportSetting: 'Event Report Setting',
    groupSetting: 'Visibility Rules（分组设置）',
    publishInfo: 'Effective Setting（发布信息）',
    basicInfo: 'Basic Info（基础信息）',
    componentStyle: 'Component Style（组件样式）',
    titleStyle: 'Title Style（标题样式）',
    staticTextStyle: 'Static Text Style（静态文本样式）',
    cardStyle: 'Card Style（卡片样式）',
  };
  return titles[panelName] || panelName;
}

// ========== 主执行函数 ==========

function main() {
  const args = process.argv.slice(2);

  if (args.length < 1) {
    console.log(`
使用方法：
  node scripts/validate-and-correct-fields.js <方案文档路径>

示例：
  node scripts/validate-and-correct-fields.js "组件方案文档.md"

输出：
  - 纠正后的文档：<原文件名>-corrected.md
  - 纠正报告：<原文件名>-correction-report.json
    `);
    process.exit(1);
  }

  const inputFile = args[0];
  const inputPath = path.resolve(inputFile);

  if (!fs.existsSync(inputPath)) {
    console.error(`错误：文件不存在 - ${inputPath}`);
    process.exit(1);
  }

  console.log('\n========== 字段规范验证和纠正工具 V2 ==========\n');
  console.log(`输入文件：${inputFile}`);

  // 读取文档
  const content = fs.readFileSync(inputPath, 'utf8');

  // 解析字段定义
  console.log('\n1. 解析方案文档...');
  const fields = parseDocument(content);
  console.log(`   总计找到 ${Object.keys(fields).length} 个字段定义`);

  // 创建验证器
  const validator = new FieldValidator();
  validator.allFields = fields;

  // 验证并纠正字段
  console.log('\n2. 验证字段规范...');
  const correctedFields = {};

  Object.entries(fields).forEach(([fieldName, fieldDef]) => {
    const corrected = validator.validateAndCorrectField(fieldName, fieldDef);
    correctedFields[corrected.name] = corrected.definition;
  });

  // 检查必需的公共字段
  console.log('\n3. 检查必需的公共字段...');
  const missingFields = validator.checkRequiredFields(correctedFields);
  validator.addedFields.push(...missingFields);
  console.log(`   缺失 ${missingFields.length} 个必需字段`);

  // 生成报告
  const report = validator.generateReport();

  // 输出验证结果
  console.log('\n========== 验证结果 ==========\n');
  console.log(`✓ 字段名称纠正：${report.corrections.filter((c) => c.type === 'name').length} 项`);
  console.log(`✓ 数据类型纠正：${report.corrections.filter((c) => c.type === 'dataType').length} 项`);
  console.log(`✓ 新增必需字段：${report.addedFields.length} 项`);

  // 生成纠正后的文档
  console.log('\n4. 生成纠正后的文档...');
  const correctedContent = generateCorrectedDocument(content, correctedFields, validator.addedFields, report);

  // 保存文件
  const outputDir = path.dirname(inputPath);
  const baseName = path.basename(inputPath, '.md');
  const correctedPath = path.join(outputDir, `${baseName}-corrected.md`);
  const reportPath = path.join(outputDir, `${baseName}-correction-report.json`);

  fs.writeFileSync(correctedPath, correctedContent);
  fs.writeFileSync(reportPath, JSON.stringify(report, null, 2));

  console.log(`\n✓ 纠正后的文档已保存：${correctedPath}`);
  console.log(`✓ 详细报告已保存：${reportPath}`);

  console.log('\n✓ 字段验证和纠正完成！');
  console.log('\n说明：纠正后的文档可作为真理源直接提供给AI使用，无需额外推理。');
}

// 执行主函数
main();
